package edu.cth.scrabbit.client.view;

import java.awt.Color;
import java.awt.Image;
import java.awt.Toolkit;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.ActionMap;
import javax.swing.GroupLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.LayoutStyle;

import org.jdesktop.application.Action;
import org.jdesktop.application.SingleFrameApplication;

import edu.cth.scrabbit.client.core.ClientModel;
import edu.cth.scrabbit.client.view.panels.ActionsPanel;
import edu.cth.scrabbit.client.view.panels.BoardPanel;
import edu.cth.scrabbit.client.view.panels.ConnectPanel;
import edu.cth.scrabbit.client.view.panels.PlayerPanel;
import edu.cth.scrabbit.client.view.panels.UserLetterPanel;
import edu.cth.scrabbit.shared.GameLetter;
import edu.cth.scrabbit.shared.GameState;
import edu.cth.scrabbit.shared.Player;

import java.awt.BorderLayout;

/**
 * This code was edited or generated using CloudGarden's Jigloo
 * SWT/Swing GUI Builder, which is free for non-commercial
 * use. If Jigloo is being used commercially (ie, by a corporation,
 * company or business for any purpose whatever) then you
 * should purchase a license for each developer using Jigloo.
 * Please visit www.cloudgarden.com for details.
 * Use of Jigloo implies acceptance of these licensing terms.
 * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
 * THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
 * LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
 */
/**
 * 
 */
public class UserView extends SingleFrameApplication implements
		PropertyChangeListener {

	private JPanel topPanel;
	private ConnectPanel connectPanel1;
	private PlayerPanel playerPanel3;
	private JMenuBar menuBar;
	private JMenuItem aboutMenuItem;
	private JMenuItem exitMenuItem;
	private JSeparator jSeparator1;
	private JMenuItem joinMenuItem;
	private JMenuItem hostMenuItem;
	private JMenu helpMenu;
	private JMenu jMenu1;
	private BoardPanel boardPanel;
	private ActionsPanel actionsPanel1;
	private UserLetterPanel userLetterPanel1;
	private PlayerPanel playerPanel4;
	private PlayerPanel playerPanel2;
	private PlayerPanel playerPanel1;
	private AboutDialog aboutDialog;
	private PlayerPanel[] playerPanels;

	@Override
	protected void startup() {
		{
			menuBar = new JMenuBar();
			getMainFrame().setJMenuBar(menuBar);
			{
				jMenu1 = new JMenu();
				menuBar.add(jMenu1);
				jMenu1.setName("jMenu1");
				{
					hostMenuItem = new JMenuItem();
					jMenu1.add(hostMenuItem);
					hostMenuItem.setName("hostMenuItem");
					hostMenuItem.setAction(getActionMap().get("hostAction"));
				}
				{
					joinMenuItem = new JMenuItem();
					jMenu1.add(joinMenuItem);
					joinMenuItem.setName("joinMenuItem");
					joinMenuItem.setAction(getActionMap().get("joinAction"));
				}
				{
					jSeparator1 = new JSeparator();
					jMenu1.add(jSeparator1);
				}
				{
					exitMenuItem = new JMenuItem();
					jMenu1.add(exitMenuItem);
					exitMenuItem.setName("exitMenuItem");
					exitMenuItem.setAction(getActionMap().get("exitAction"));
				}
			}
			{
				helpMenu = new JMenu();
				menuBar.add(helpMenu);
				helpMenu.setName("helpMenu");
				{
					aboutMenuItem = new JMenuItem();
					helpMenu.add(aboutMenuItem);
					aboutMenuItem.setName("aboutMenuItem");
					aboutMenuItem.setAction(getActionMap().get("aboutAction"));
				}
			}
		}
		
		{
			topPanel = new JPanel();
			getMainFrame().getContentPane().add(topPanel, BorderLayout.NORTH);
			GroupLayout topPanelLayout = new GroupLayout((JComponent) topPanel);
			topPanel.setLayout(topPanelLayout);
			topPanel.setPreferredSize(new java.awt.Dimension(784, 617));
			topPanel.setBackground(Color.DARK_GRAY);
			{
				boardPanel = new BoardPanel();
			}
			{
				connectPanel1 = new ConnectPanel();
			}
			{
				actionsPanel1 = new ActionsPanel();
			}
			{
				playerPanel1 = new PlayerPanel();
			}
			{
				playerPanel2 = new PlayerPanel();
			}
			{
				playerPanel3 = new PlayerPanel();
			}
			{
				playerPanel4 = new PlayerPanel();
				playerPanel4.setSize(162, 57);
			}
			{
				userLetterPanel1 = new UserLetterPanel();
			}
			topPanelLayout.setHorizontalGroup(topPanelLayout.createSequentialGroup()
				.addGroup(topPanelLayout.createParallelGroup()
				    .addComponent(boardPanel, GroupLayout.Alignment.LEADING, GroupLayout.PREFERRED_SIZE, 613, GroupLayout.PREFERRED_SIZE)
				    .addGroup(GroupLayout.Alignment.LEADING, topPanelLayout.createSequentialGroup()
				        .addGap(104)
				        .addComponent(userLetterPanel1, GroupLayout.PREFERRED_SIZE, 373, GroupLayout.PREFERRED_SIZE)
				        .addGap(136)))
				.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
				.addGroup(topPanelLayout.createParallelGroup()
				    .addGroup(GroupLayout.Alignment.LEADING, topPanelLayout.createSequentialGroup()
				        .addComponent(playerPanel1, 0, 145, Short.MAX_VALUE)
				        .addGap(6))
				    .addGroup(GroupLayout.Alignment.LEADING, topPanelLayout.createSequentialGroup()
				        .addComponent(playerPanel2, 0, 145, Short.MAX_VALUE)
				        .addGap(6))
				    .addGroup(GroupLayout.Alignment.LEADING, topPanelLayout.createSequentialGroup()
				        .addComponent(playerPanel3, 0, 145, Short.MAX_VALUE)
				        .addGap(6))
				    .addComponent(actionsPanel1, GroupLayout.Alignment.LEADING, GroupLayout.PREFERRED_SIZE, 151, GroupLayout.PREFERRED_SIZE)
				    .addComponent(connectPanel1, GroupLayout.Alignment.LEADING, GroupLayout.PREFERRED_SIZE, 151, GroupLayout.PREFERRED_SIZE)
				    .addGroup(GroupLayout.Alignment.LEADING, topPanelLayout.createSequentialGroup()
				        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
				        .addComponent(playerPanel4, 0, 145, Short.MAX_VALUE)
				        .addGap(6))));
			topPanelLayout.setVerticalGroup(topPanelLayout.createSequentialGroup()
				.addGroup(topPanelLayout.createParallelGroup()
				    .addGroup(GroupLayout.Alignment.LEADING, topPanelLayout.createSequentialGroup()
				        .addComponent(connectPanel1, GroupLayout.PREFERRED_SIZE, 105, GroupLayout.PREFERRED_SIZE)
				        .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				        .addComponent(playerPanel1, GroupLayout.PREFERRED_SIZE, 51, GroupLayout.PREFERRED_SIZE)
				        .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				        .addComponent(playerPanel2, GroupLayout.PREFERRED_SIZE, 34, GroupLayout.PREFERRED_SIZE)
				        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
				        .addComponent(playerPanel3, GroupLayout.PREFERRED_SIZE, 38, GroupLayout.PREFERRED_SIZE)
				        .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				        .addComponent(playerPanel4, GroupLayout.PREFERRED_SIZE, 43, GroupLayout.PREFERRED_SIZE)
				        .addGap(0, 102, Short.MAX_VALUE)
				        .addComponent(actionsPanel1, GroupLayout.PREFERRED_SIZE, 145, GroupLayout.PREFERRED_SIZE)
				        .addGap(18))
				    .addGroup(topPanelLayout.createSequentialGroup()
				        .addComponent(boardPanel, GroupLayout.PREFERRED_SIZE, 575, GroupLayout.PREFERRED_SIZE)
				        .addGap(0, 0, Short.MAX_VALUE)))
				.addComponent(userLetterPanel1, GroupLayout.PREFERRED_SIZE, 62, GroupLayout.PREFERRED_SIZE));
		}
		getMainFrame().setSize(780, 700);
		show(topPanel);
			
		// Non-generated code:
		ClientModel.getInstance().addObserver(this);

		playerPanels = new PlayerPanel[4];

		playerPanels[0] = playerPanel1;
		playerPanels[1] = playerPanel2;
		playerPanels[2] = playerPanel3;
		playerPanels[3] = playerPanel4;
		
		//Set the icon of the application
		Image icon = Toolkit.getDefaultToolkit().getImage(
				this.getMainFrame().getClass().getResource(
						"/edu/cth/scrabbit/client/view/resources/icon/bild.png"));
		this.getMainFrame().setIconImage(icon);
		
		
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		String stateName = evt.getPropertyName();
		if (stateName.equalsIgnoreCase("GameState")) {
			GameState state = (GameState) evt.getNewValue();
			setPlayerInfo(state);
			setLetterMatrixSoft(state.getLetterMatrix());
			userLetterPanel1.setLetters(state.getOwnLetters());
			if (state.hasGameStarted()) {
				changePlayerPanelColors(state.getCurrentPlayer());
			}
		}

		else if (stateName.equalsIgnoreCase("Clear_Gameboard")) {
			GameLetter[][] matrix = (GameLetter[][]) evt.getNewValue();
			setLetterMatrixHard(matrix);
			userLetterPanel1.setEnableAllButtons(true);
		}

		else if (stateName.equalsIgnoreCase("Letter_Update")) {
			GameLetter letter = (GameLetter) evt.getNewValue();
			boardPanel.setLetterInfo(letter, letter.getXIndex(),
					letter.getYIndex());
			userLetterPanel1.disableButton(letter);
		}

		else if (stateName.equalsIgnoreCase("Disable_Connect")) {
			connectPanel1.setConnectEnabled(false);
			joinMenuItem.setEnabled(false);
			hostMenuItem.setEnabled(false);
		}

		else if (stateName.equalsIgnoreCase("Enable_Start")) {
			connectPanel1.setStartButtonEnabled(true);
		}

		else if (stateName.equalsIgnoreCase("Disable_Start")) {
			connectPanel1.setStartButtonEnabled(false);
		}

		else if (stateName.equalsIgnoreCase("Disable_Play")) {
			actionsPanel1.setButtonsEnabled(false);
		}

		else if (stateName.equalsIgnoreCase("Enable_Play")) {
			actionsPanel1.setButtonsEnabled(true);
		}

		else if (stateName.equalsIgnoreCase("New_CurrentPlayer")) {
			boolean thisPlayer = (Boolean) evt.getNewValue();
			userLetterPanel1.setEnableAllButtons(thisPlayer);
		}

		else if (stateName.equalsIgnoreCase("Game_Over")) {
			Player winner = (Player) evt.getNewValue();

			String message = "The game is over! The winner is "
					+ winner.getName() + " with " + winner.getScore()
					+ " points";
			JOptionPane.showMessageDialog(null, message);
		}
	}

	/*
	 * Setting letters on the gameboard, represented as a matrix. Overwrites all
	 * letters currently on the board
	 */
	private void setLetterMatrixHard(GameLetter[][] matrix) {
		for (int i = 0; i < matrix.length; i++) {
			GameLetter[] glRow = matrix[i];
			for (int j = 0; j < glRow.length; j++) {
				GameLetter letter = matrix[j][i];
				boardPanel.setLetterInfo(letter, i, j);
			}
		}
	}

	/*
	 * Setting letters on the gameboard, represented as a matrix. Overwrites
	 * only dummy letters on the board
	 */
	private void setLetterMatrixSoft(GameLetter[][] matrix) {
		for (int i = 0; i < matrix.length; i++) {
			for (int j = 0; j < matrix[i].length; j++) {
				GameLetter existing = boardPanel.getLetterInfo(i, j);
				if (existing == null || existing.isDummy()) {
					boardPanel.setLetterInfo(matrix[j][i], i, j);
				}
			}
		}
	}

	private void changePlayerPanelColors(int index) {
		for (int i = 0; i < playerPanels.length; i++) {
			playerPanels[i].setBackgroundColor(i == index);
		}
	}

	/**
	 * Setting a name and a score for a player to the playerpanels
	 * 
	 * @param state
	 */
	private void setPlayerInfo(GameState state) {
		for (int i = 0; i < state.getPlayers().length; i++) {
			Player player = state.getPlayers()[i];

			if (player != null) {
				int position = player.getPosition();
				PlayerPanel pp = playerPanels[position];
				pp.setPlayerName(player.getName());
				pp.setScore(player.getScore());
			}
		}
	}
	@Action
	public void hostAction(){
		connectPanel1.hostGameAction();
	}
	@Action
	public void joinAction(){
		connectPanel1.joinGameAction();
	}
	@Action
	public void aboutAction() {
		if (aboutDialog == null) {
			aboutDialog = new AboutDialog(new JFrame());
		}
		aboutDialog.setVisible(true);
	}
	@Action
	public void exitAction(){
		this.exit();
	}
	private ActionMap getActionMap() {
		return getInstance().getContext().getActionMap(this);
	}
}
